import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class CommonTabBar extends StatelessWidget {
  const CommonTabBar({
    super.key,
    required this.titles,
    this.titleWidget,
    this.fontSize = 15,
    this.unselectedFontSize = 15,
    this.indicatorColor = Colors.black,
    this.tabController,
    this.tabIndicatorInsets,
    this.height,
    this.unselectedLabelColor = const Color(0XFF4E5969),
    this.isScrollable = false,
    this.labelPadding,
    this.indicatorHeight,
    this.fontWeight = FontWeight.bold,
    this.unselectedFontWeight = FontWeight.normal,
  });

  final List<String> titles;
  final List<Widget>? titleWidget;
  final double? fontSize;
  final double? unselectedFontSize;
  final Color indicatorColor;
  final TabController? tabController;
  final EdgeInsets? tabIndicatorInsets;
  final double? height;
  final Color unselectedLabelColor;
  final bool isScrollable;
  final EdgeInsets? labelPadding;
  final double? indicatorHeight;
  final FontWeight? fontWeight;
  final FontWeight? unselectedFontWeight;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: height ?? 40.w,
      child: TabBar(
        controller: tabController,
        labelPadding: labelPadding ?? EdgeInsets.zero,
        isScrollable: isScrollable,
        indicator: CommonTabIndicator(
          borderSide: BorderSide(width: indicatorHeight ?? 2.w, color: indicatorColor),
          insets: tabIndicatorInsets ?? EdgeInsets.fromLTRB(3.w, 0, 3.w, 5.w),
        ),
        indicatorSize: TabBarIndicatorSize.label,
        labelColor: Colors.black,
        labelStyle: TextStyle(fontSize: fontSize, fontWeight: fontWeight),
        unselectedLabelColor: unselectedLabelColor,
        unselectedLabelStyle: TextStyle(fontSize: fontSize, fontWeight: unselectedFontWeight),
        tabs: titleWidget ?? titles.map((e) => Tab(text: e)).toList(),
      ),
    );
  }
}

class CommonTabIndicator extends Decoration {
  const CommonTabIndicator({
    this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
    this.insets = EdgeInsets.zero,
  });

  final BorderSide borderSide;

  final EdgeInsetsGeometry insets;

  @override
  Decoration? lerpFrom(Decoration? a, double t) {
    if (a is CommonTabIndicator) {
      return CommonTabIndicator(
        borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
        insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  Decoration? lerpTo(Decoration? b, double t) {
    if (b is CommonTabIndicator) {
      return CommonTabIndicator(
        borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
        insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return _CommonTabIndicatorPainter(this, onChanged);
  }

  Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
    final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
    return Rect.fromLTWH(
      indicator.left,
      indicator.bottom - borderSide.width,
      indicator.width,
      borderSide.width,
    );
  }

  @override
  Path getClipPath(Rect rect, TextDirection textDirection) {
    return Path()..addRect(_indicatorRectFor(rect, textDirection));
  }
}

class _CommonTabIndicatorPainter extends BoxPainter {
  _CommonTabIndicatorPainter(this.decoration, VoidCallback? onChanged) : super(onChanged);

  final CommonTabIndicator decoration;

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration.size != null);
    final Rect rect = offset & configuration.size!;
    final TextDirection textDirection = configuration.textDirection!;
    final Rect indicator = decoration._indicatorRectFor(rect, textDirection).deflate(decoration.borderSide.width / 2.0);
    final Paint paint = decoration.borderSide.toPaint()..strokeCap = StrokeCap.round;
    canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
  }
}
